package com.telit.common.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotBlank;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;


@Component
public class RedisUtils {

    private static String prefix;
    //在实际项目中每一个项目都应该有对应的项目缓存前缀
    @Value("${spring.redis.prefix:FIRE:YICHANG:}")
    private void setPrefix(String prefix) {
        RedisUtils.prefix = prefix + ":";
    }
    public static String getPrefix() {
        return prefix;
    }

//    @Autowired
    private  static StringRedisTemplate redisTemplate;

    @Autowired
    public RedisUtils(StringRedisTemplate redisTemplate){
        RedisUtils.redisTemplate = redisTemplate;
    }

    /**
     * 批量删除对应的value
     *
     * @param keys
     */
    public static void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }

    }
    /**
     * 批量删除key
     *
     * @param pattern
     */
    public static void removePattern(final String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys.size() > 0){
            redisTemplate.delete(keys);
        }
    }
    /**
     * 删除对应的value
     *
     * @param key
     */
    public static void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }
    /**
     * 判断缓存中是否有对应的value
     *
     * @param key
     * @return
     */
    public static boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public static String get(final String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean set(final String key, String value) {
        redisTemplate.opsForValue().set(key, value);
        return true;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setIfPresent(final String key, String value) {
        redisTemplate.opsForValue().setIfPresent(key, value);
        return true;
    }


    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean set(final String key, String value, Long expireTime) {
        redisTemplate.opsForValue().set(key, value);
        redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        return true;
    }

    /**
     * 为多个哈希字段分别设置它们的值
     * @param key,value
     * @return boolean
     **/
    public static boolean hmset(String key, Map<String, String> value) {
        redisTemplate.opsForHash().putAll(key, value);
        return true;
    }

    /**
     * 获取所有给定哈希字段的值
     * @return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 获取hash字段中的某一个值
     * @param key
     * @param value
     * @return
     */
    public static Object hmgetOne(String key, String value){
        return redisTemplate.opsForHash().get(key,value);
    }

    /**
     * 进队列
     * @param key, value
     * @return boolean
     **/
    public static boolean hmPushList(String key, String value){
        redisTemplate.opsForList().leftPush(key, value);
        return true;
    }

    /**
     * 出队列
     * @return boolean
     **/
    public static String hmPopList(String key){
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 读list中所有数据
     * @param key
     * @return
     */
    public static List<String> hmGetList(String key){
        return redisTemplate.opsForList().range(key,0,-1);
    }


    /**
     * 同步更改
     * @return java.lang.String
     **/
    public static String getAndSet(String key, String newValue){
        return redisTemplate.opsForValue().getAndSet(key, newValue);
    }

    /**
     * 同步更改
     * @return java.lang.String
     **/
    public static String getAndSetWithExpire(String key, String newValue, long expireTime){
        String oldValue = redisTemplate.opsForValue().getAndSet(key, newValue);
        redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        return oldValue;
    }

    /**
     *  hash 存储对应一个value
     * @return
     */
    public static boolean setBoundHash(String key,String field,String value){
        redisTemplate.boundHashOps(key).put(field,value);
        return true;
    }

    /**
     * 获取对应hash中某一个值
     * @param key
     * @param field
     * @return
     */
    public static Object getBoundHash(String key, String field){
        return redisTemplate.boundHashOps(key).get(field);
    }

    /**
     *  hash 清除缓存
     * @return
     */
    public static boolean removeBoundHash(String key,String field){
        redisTemplate.boundHashOps(key).delete(field);
        return true;
    }

    /**
     * 根据key表达式  删除所有匹配上的key
     */
    public static void deleteByPattern(@NotBlank String keyPattern) {
        Set<String> keys = keys(keyPattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }

    /**
     * other
     */
    // 获取所有匹配此字符串的key
    public static Set<String> keys(@NotBlank String pattern) {
        // 2020-04-16 调整keys的获取方式
        return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> binaryKeys = new HashSet<>();
            try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(prefix + pattern).count(10_000).build())) {
                while (cursor.hasNext()) {
                    binaryKeys.add(new String(cursor.next()));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return binaryKeys;
        });
    }

//
//    public static Object getObject(@NotBlank String key) {
//        return redisTemplate.opsForValue().get(prefix + key);
//    }



//    // 设置key-value并指定生存时间，单位 秒
//    public static void setObject(@NotBlank String key, @NotNull Object value, int timeOutSeconds) {
//        redisTemplate.opsForValue().set(prefix + key, value, timeOutSeconds, TimeUnit.SECONDS);
//    }
//    /** set Object */
//    public static void setObject(@NotBlank String key, @NotNull Object value) {
//        redisTemplate.opsForValue().set(prefix + key, value);
//    }


}
